/**
 * 智能地理编码服务 - 结合BIM数据
 * 1. 使用高德地图获取小区基础位置
 * 2. 结合BIM数据中的建筑坐标进行精确定位
 */

// 日志工具类
class Logger {
    constructor() {
        this.logs = []
    }

    info(message) {
        const timestamp = new Date().toISOString()
        const logMessage = `${timestamp} - INFO - ${message}`
        console.log(logMessage)
        this.logs.push(logMessage)
    }

    error(message) {
        const timestamp = new Date().toISOString()
        const logMessage = `${timestamp} - ERROR - ${message}`
        console.error(logMessage)
        this.logs.push(logMessage)
    }

    warning(message) {
        const timestamp = new Date().toISOString()
        const logMessage = `${timestamp} - WARNING - ${message}`
        console.warn(logMessage)
        this.logs.push(logMessage)
    }

    getLogs() {
        return this.logs.join('\n')
    }
}

const logger = new Logger()

/**
 * 智能地理编码器 - 结合高德地图和BIM数据
 */
class SmartGeocoder {
    constructor(apiKey) {
        this.apiKey = apiKey
        this.baseUrl = 'https://restapi.amap.com/v3/geocode/geo'
        this.bimData = {}
    }

    /**
     * 获取小区的基础坐标
     * @param {string} communityName 小区名称
     * @returns {Promise<Object>} 地理编码结果
     */
    async geocodeCommunity(communityName) {
        const params = new URLSearchParams({
            key: this.apiKey,
            address: communityName,
            output: 'json',
        })

        const response = await fetch(`${this.baseUrl}?${params}`, {
            method: 'GET',
            timeout: 10000,
        })

        return await response.json()
    }

    /**
     * 根据建筑编号获取精确坐标
     * @param {string} buildingNumber 建筑编号
     * @param {string} roomNumber 房间编号
     * @returns {Object|null} 坐标数据
     */
    getBuildingCoordinates(buildingNumber, roomNumber = null) {
        // 1. 首先尝试精确匹配房间ID
        if (roomNumber) {
            // 构建可能的房间ID格式
            const possibleIds = [
                `兴海嘉苑-${buildingNumber}-${roomNumber}`,
                `安滨嘉苑-${buildingNumber}-${roomNumber}`,
                `${buildingNumber}-${roomNumber}`,
            ]

            for (const roomId of possibleIds) {
                if (this.bimData[roomId]) {
                    return this.bimData[roomId]
                }
            }
        }

        // 2. 尝试匹配建筑编号
        if (this.bimData[buildingNumber]) {
            return this.bimData[buildingNumber]
        }

        // 3. 尝试模糊匹配
        for (const [key, data] of Object.entries(this.bimData)) {
            if (key.includes(buildingNumber)) {
                return data
            }
        }

        return null
    }

    /**
     * 计算建筑物相对于小区中心的偏移量
     * @param {number} baseLat 基础纬度
     * @param {number} baseLng 基础经度
     * @param {string} buildingNumber 建筑编号
     * @param {number} index 索引
     * @returns {Array} [offsetLat, offsetLng]
     */
    calculateOffset(baseLat, baseLng, buildingNumber, index) {
        // 根据建筑编号计算偏移
        // 这是一个简单的算法，实际应用中可能需要更复杂的布局算法

        // 提取建筑编号中的数字
        const match = buildingNumber.match(/(\d+)/)
        let buildingNum = index

        if (match) {
            buildingNum = parseInt(match[1])
        }

        // 计算行列位置（假设建筑按网格排列）
        const row = Math.floor((buildingNum - 1) / 10)
        const col = (buildingNum - 1) % 10

        // 每栋楼之间的间距（经纬度）
        const spacingLat = 0.0002 // 约22米
        const spacingLng = 0.0003 // 约30米

        // 计算偏移后的坐标
        const offsetLat = baseLat + (row - 5) * spacingLat
        const offsetLng = baseLng + (col - 5) * spacingLng

        return [offsetLat, offsetLng]
    }
}

/**
 * Excel数据处理工具类
 */
class ExcelProcessor {
    /**
     * 读取Excel文件（在浏览器中通过文件输入）
     * @param {File} file Excel文件
     * @returns {Promise<Array>} 数据数组
     */
    static async readExcelFile(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader()

            reader.onload = function (e) {
                try {
                    // 这里需要引入一个Excel解析库，如xlsx
                    // 为了简化，这里假设数据已经是JSON格式
                    const data = JSON.parse(e.target.result)
                    resolve(data)
                } catch (error) {
                    reject(error)
                }
            }

            reader.onerror = function () {
                reject(new Error('文件读取失败'))
            }

            reader.readAsText(file)
        })
    }

    /**
     * 导出数据为Excel文件
     * @param {Array} data 数据数组
     * @param {string} filename 文件名
     */
    static exportToExcel(data, filename) {
        // 创建CSV格式的数据
        const headers = Object.keys(data[0] || {})
        const csvContent = [
            headers.join(','),
            ...data.map(row =>
                headers
                    .map(header => JSON.stringify(row[header] || ''))
                    .join(',')
            ),
        ].join('\n')

        // 创建下载链接
        const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })
        const link = document.createElement('a')

        if (link.download !== undefined) {
            const url = URL.createObjectURL(blob)
            link.setAttribute('href', url)
            link.setAttribute('download', filename)
            link.style.visibility = 'hidden'
            document.body.appendChild(link)
            link.click()
            document.body.removeChild(link)
        }
    }
}

/**
 * 处理房产数据 - 结合BIM坐标
 * @param {string} apiKey 高德地图API密钥
 * @param {Array} houseData 房产数据数组
 */
async function processHouseDataWithBIM(apiKey, houseData) {
    logger.info('开始处理房产权属数据（结合BIM数据）...')

    if (!houseData || houseData.length === 0) {
        logger.error('没有提供房产数据！')
        return
    }

    logger.info(`成功读取 ${houseData.length} 条记录`)
    logger.info(`列名: ${Object.keys(houseData[0] || {})}`)

    // 创建智能地理编码器
    const geocoder = new SmartGeocoder(apiKey)

    // 初始化结果数据
    const processedData = houseData.map(row => ({
        ...row,
        longitude: null,
        latitude: null,
        geocodeMethod: '',
        geocodeConfidence: 0.0,
        formattedAddress: '',
        province: '',
        city: '',
        district: '',
    }))

    // 统计
    const stats = {
        bimExact: 0, // BIM精确匹配
        bimBuilding: 0, // BIM建筑匹配
        calculated: 0, // 计算得出
        communityCenter: 0, // 小区中心点
        failed: 0, // 失败
    }

    // 获取小区基础坐标
    let communityResult = null
    const firstRow = houseData[0]
    if (firstRow && firstRow.xqname) {
        const xqname = firstRow.xqname
        if (xqname) {
            logger.info(`获取小区 '${xqname}' 的基础坐标...`)
            communityResult = await geocoder.geocodeCommunity(String(xqname))
            if (communityResult.success) {
                logger.info(
                    `小区中心坐标: (${communityResult.longitude}, ${communityResult.latitude})`
                )
            }
        }
    }

    // 处理每条记录
    for (let index = 0; index < processedData.length; index++) {
        const row = processedData[index]
        logger.info(`\n处理 [${index + 1}/${processedData.length}]:`)

        const buildingNumber = (row.building_number || '').toString().trim()
        const roomNumber = (row.room_number || '').toString().trim()

        // 1. 尝试从BIM数据获取精确坐标
        const bimCoords = geocoder.getBuildingCoordinates(
            buildingNumber,
            roomNumber
        )

        if (bimCoords) {
            row.longitude = bimCoords.longitude
            row.latitude = bimCoords.latitude
            row.geocodeMethod = roomNumber ? 'BIM精确匹配' : 'BIM建筑匹配'
            row.geocodeConfidence = roomNumber ? 1.0 : 0.9

            if (roomNumber) {
                stats.bimExact++
            } else {
                stats.bimBuilding++
            }

            logger.info(
                `  ${buildingNumber} ${roomNumber} -> BIM坐标: (${bimCoords.longitude}, ${bimCoords.latitude})`
            )
        }
        // 2. 如果没有BIM数据，使用小区中心点+偏移计算
        else if (communityResult && communityResult.success && buildingNumber) {
            const [offsetLat, offsetLng] = geocoder.calculateOffset(
                communityResult.latitude,
                communityResult.longitude,
                buildingNumber,
                index
            )

            row.longitude = offsetLng
            row.latitude = offsetLat
            row.geocodeMethod = '基于小区中心计算'
            row.geocodeConfidence = 0.7
            stats.calculated++

            logger.info(
                `  ${buildingNumber} -> 计算坐标: (${offsetLng}, ${offsetLat})`
            )
        }
        // 3. 使用小区中心点
        else if (communityResult && communityResult.success) {
            row.longitude = communityResult.longitude
            row.latitude = communityResult.latitude
            row.geocodeMethod = '小区中心点'
            row.geocodeConfidence = 0.5
            stats.communityCenter++

            logger.info(
                `  使用小区中心点: (${communityResult.longitude}, ${communityResult.latitude})`
            )
        } else {
            row.geocodeMethod = '失败'
            row.geocodeConfidence = 0.0
            stats.failed++
            logger.warning(`  无法获取坐标`)
        }

        // 填充地址信息
        if (communityResult && communityResult.success) {
            row.formattedAddress = communityResult.formattedAddress || ''
            row.province = communityResult.province || ''
            row.city = communityResult.city || ''
            row.district = communityResult.district || ''
        }
    }

    // 保存结果
    const timestamp = new Date()
        .toISOString()
        .replace(/[:.]/g, '-')
        .slice(0, 19)
    const outputFilename = `house_owner_geocoded_bim_${timestamp}.csv`

    ExcelProcessor.exportToExcel(processedData, outputFilename)
    logger.info(`\n结果已保存到: ${outputFilename}`)

    // 生成详细报告
    const report = `
地理编码完成报告（结合BIM数据）
================================
处理时间: ${new Date().toLocaleString()}
总记录数: ${processedData.length}

坐标获取方式统计:
  BIM精确匹配: ${stats.bimExact} 条
  BIM建筑匹配: ${stats.bimBuilding} 条
  基于小区计算: ${stats.calculated} 条
  小区中心点: ${stats.communityCenter} 条
  失败: ${stats.failed} 条

成功率: ${(
        ((processedData.length - stats.failed) / processedData.length) *
        100
    ).toFixed(2)}%
`

    // 添加坐标范围统计
    const validData = processedData.filter(row => row.longitude !== null)
    if (validData.length > 0) {
        const longitudes = validData.map(row => row.longitude)
        const latitudes = validData.map(row => row.latitude)

        const lonRange = [Math.min(...longitudes), Math.max(...longitudes)]
        const latRange = [Math.min(...latitudes), Math.max(...latitudes)]

        const uniqueLongitudes = new Set(longitudes).size
        const uniqueLatitudes = new Set(latitudes).size

        report += `
坐标范围:
  经度: ${lonRange[0].toFixed(6)} ~ ${lonRange[1].toFixed(6)}
  纬度: ${latRange[0].toFixed(6)} ~ ${latRange[1].toFixed(6)}
  
坐标分布:
  不同经度值: ${uniqueLongitudes} 个
  不同纬度值: ${uniqueLatitudes} 个
`
    }

    // 保存报告
    const reportFilename = `house_owner_geocoded_bim_${timestamp}_report.txt`
    const reportBlob = new Blob([report], { type: 'text/plain;charset=utf-8' })
    const reportLink = document.createElement('a')
    reportLink.href = URL.createObjectURL(reportBlob)
    reportLink.download = reportFilename
    reportLink.click()

    logger.info(`报告已保存到: ${reportFilename}`)
    logger.info(`\n${report}`)

    // 显示部分结果示例
    logger.info(`\n结果示例（前10条不同坐标）:`)
    const seenCoords = new Set()
    const sampleData = validData
        .filter(row => {
            const coordKey = `${row.longitude},${row.latitude}`
            if (seenCoords.has(coordKey)) return false
            seenCoords.add(coordKey)
            return true
        })
        .slice(0, 10)

    sampleData.forEach(row => {
        logger.info(
            `  ${row.building_number || ''} ${row.room_number || ''} -> ` +
                `(${row.longitude.toFixed(6)}, ${row.latitude.toFixed(6)}) - ${
                    row.geocodeMethod
                }`
        )
    })

    return processedData
}

/**
 * 主函数
 */
async function main() {
    const API_KEY = '64fdb23b96e7a2c0c94c95a789ecef50'

    logger.info('='.repeat(60))
    logger.info('智能地理编码服务 - 结合BIM数据')
    logger.info('='.repeat(60))

    // 检查必要文件
    if (typeof window.bimData === 'undefined') {
        logger.warning('未找到BIM数据，将尝试从页面中提取...')
    }

    // 返回处理函数供外部调用
    return {
        processHouseDataWithBIM: houseData =>
            processHouseDataWithBIM(API_KEY, houseData),
        SmartGeocoder,
        BIMDataExtractor,
        ExcelProcessor,
        logger,
    }
}

// 导出模块
if (typeof module !== 'undefined' && module.exports) {
    module.exports = {
        main,
        SmartGeocoder,
        BIMDataExtractor,
        ExcelProcessor,
        Logger,
    }
} else {
    // 浏览器环境
    window.GeocodingWithBIM = {
        main,
        SmartGeocoder,
        BIMDataExtractor,
        ExcelProcessor,
        Logger,
    }
}

// 自动初始化
if (typeof window !== 'undefined') {
    window.addEventListener('DOMContentLoaded', () => {
        main().then(geocodingService => {
            window.geocodingService = geocodingService
            console.log('智能地理编码服务已加载完成')
        })
    })
}
